#!/usr/bin/python

"""
 Module: getnetstream (gns.py)
 Ver: 1.0.0; Rev Last 12/24/2012, Previous 12/22/2012  (AEM)
 Original Release; 12/24/2012

 Rev 1.0.1; Last: 01/26/2013 - Previous: 01/25/2013 (AEM)
   - Add save last state at shutdown
   - Add recall and restore last state at startup
   - Updated associated comments

 Rev: 1.0.2; Rev Last: 02/05/2013 - Previous: 02/04/2013 (AEM)
   - Add module cleanmove.py to clean new file names captured
     by Get Net Stream.

 Rev: 1.0.3; Rev Last: 02/13/2013 - Previous: 02/05/2013 (AEM)
   - Update to README doc

 Rev: 1.0.4; Rev Last: 02/22/2013 - Previous: 02/13/2013 (AEM)
   - Widen the clean and move frame (cleanmove.py)
   - Add total files in target dir to clean stats (cleanmove.py)

 This is the main program providing control logic and UI

 - Custom modules needed by this appl
   - getradiostream.py:  Thread process to do the stream capture
   - maingui.py:         Contains the main definitions for the GUI
   - cfginit.py:         Read and return values from cfg file
   - cleanmove.py:       Clean file names as saved by Streamripper
                         and copy or move from the working/capture
                         directory to a designated genre directory.
 Dependencies
   - streamripper:
       install on Ubuntu/Debian: sudo apt-get install streamripper
       install on Fedora: su -c 'yum install streamripper'
          (may require configuration of rpmfusion first)

   - wxPython:
       install on Ubuntu/Debian: sudo apt-get install python-wxtools
       install on Fedora: su -c 'yum install wxPython.i686'


 Required local settings:
   Without these defined, this program really has no purpose
   - self.StreamName            List of stream names
   - self.StreamURL             List of stream URLs
   - self.StreamLoc             List of stream save directories

   - self.DefMusicDir           When importing from a pls file and no
                                save dir specified, use this one

 Copyright (C) 2012-2013  Arnold E. Morgan

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""

import wx
import time
import datetime
import os
import sys
import logging
import threading
import cPickle

# *** Custom Modules ***
import cfginit
import maingui
import getradiostream
import cleanmove
# -----------------------------------------------------


class MssgStatusBar(wx.StatusBar):
   """ Create a 2 cell status bar """

   def __init__(self, parent):
      wx.StatusBar.__init__(self, parent)

      self.SetFieldsCount(2)
      self.SetStatusText('Welcome to GetNetStream', 0)
      self.SetStatusWidths([-5, -2])
# -----------------------------------------------------


class MainStreamFrame(wx.Frame):
   """ The application main frame.

    Segregated into 5 sections: main menu, Stream List (Progress) panel,
    Stream Action Info panel, Connect Info panel, status bar.

    Enables capturing of Internet radio streams and saving the
    resultant music files to disk.

   """

   def __init__(self, parent, ID, title, theDebugLevel):
      """ Create, place and initialize all the GUI elements. """

      wx.Frame.__init__(self, parent, ID, title, size=(1000, 900))

      # Class level attributes.
      self.LastStateFile = "laststate"   # Name of the file that holds the
                                         # last operating state at pgm
                                         # shutdown. Values are reset at
                                         # application start up.

      self.LastEndTime = ""              # Stream end time last used.
                                         # Assigned from LastStateFile.
      self.LastStreamName = ""           # Stream source name last used.
                                         # Assigned from LastStateFile.

      self.IdlePanelColor = '#2CB7F3'    # Panel color when not streaming
      self.LivePanelColor = '#07BFA6'    # Panel color during streaming process

      self.ProgramShutdownOK = False     # Controls action of the window close
                                         # button (the 'x' in the upper
                                         # right-hand corner of the window).

      # The stream list control populates with the in-progress stream
      # activity.
      self.StreamListCtrl = None
      self.StreamChild = None            # Child thread in which the
                                         # streamripper subprocess will
                                         # live and breath.

      self.IsLogging = False              # Logging decision set in cfg file
      self.appDebugLevel = theDebugLevel  # Applicaton-wide debug flag
                                          # Set the amount of run time
                                          # debug and info messaging
      # Stream ripping attributes
      # Values come from cfg file
      self.StreamRipLoc = ''             # Location of streamripper lib
      self.StreamName = []               # Displayed name of the stream
      self.StreamURL = []                # Where in the cloud to get the stream
      self.StreamLoc = []                # Where the stream files are saved

      # Default location of stream files when
      # importing new streams from a pls file.
      # Defined in the cfg file.
      # Create if the full path doesn't exist.
      self.DefMusicDir = ""

      # Get and set installation specific config values.
      (rtnstat, Mssg) = self.set_config()
      if not rtnstat:
         logging.error(Mssg)
         wx.MessageBox(Mssg, 'Info', wx.OK | wx.ICON_INFORMATION)
         self.Close(True)
      else:
         logging.debug('Config file values set ok')

      # ------- Menu ---------
      self.create_menu()
      # ---------------------

      # --------- Initialize StatusBar Text ----------
      self.MainStatusBar = MssgStatusBar(self)
      self.SetStatusBar(self.MainStatusBar)
      CurrentDT = datetime.datetime.now()
      FormattedDT = CurrentDT.strftime("%Y-%m-%d %H:%M:%S")
      self.MainStatusBar.SetStatusText(FormattedDT, 1)
      # ----------------------------------------------

      # An idea for another time
      #MyHome = os.path.expanduser('~')
      #self.MainStatusBar.SetStatusText(MyHome,0)

      # ----------- Init main panels/sizers -----------------
      maingui.init_sizers(self)

      # ---------------- Stream Action Panel ----------------
      maingui.set_stream_action_panel(self)

      # ---------------- Connect Info Panel -----------------
      maingui.set_connect_info_panel(self)

      #-------------------------------------------------------
      hbox = wx.BoxSizer(wx.HORIZONTAL)
      hbox.Add(self.StreamActionPanel, 4, wx.EXPAND | wx.ALL)
      hbox.Add(self.ConnectInfoPanel, 3, wx.EXPAND)

      self.vbox0.Add(hbox, 10, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)
      self.SetAutoLayout(True)
      self.SetSizer(self.vbox0)
      self.Layout()

      self.init_stream_ctrls()

      # And finally, capture the window close event
      self.Bind(wx.EVT_CLOSE, self.on_close_window)
      # *** End of MainTagFrame __init__ ***
      #------------------------------------------------------------------------

   def on_close_window(self, event):
      """ The final actions to destroy the main frame.

      If clicked the window close 'x' button, make the appropriate checks
      for active threads before exiting the application.
      This is also the final exit point for all user initiated
      end program actions - Exit menu, End Session button.
      """

      if self.ProgramShutdownOK:
         self.Destroy()
      else:
         OkToShutDown = self.end_this_session()
         if OkToShutDown:
            self.Destroy()
         else:
            maingui.enable_stream_action_ctrls(self)

   def save_last_state(self):
      """ Save important operating values.

      Before shutting down, save any key values we want to recall
      at program start up time.
      """      

      # The current stream name
      StreamName = self.StreamSelect.GetValue()
      # The current end time
      StreamEndTime = self.EndTimeBox.GetValue()
      StateMssg = ""

      StateVals = [StreamName, StreamEndTime]
      try:
         StateFile = open(self.LastStateFile, 'w')
         cPickle.dump(StateVals, StateFile)
         StateFile.close()
      except IOError, (errno, strerror):
         StateMssg = "State file save error(%s): %s" % (errno, strerror)
         #print StateMssg
      except:
         StateMssg = "Unexpected state file save error: ", sys.exc_info()[0]
         #print StateMssg
      finally:
         pass
      
      if len(StateMssg) > 0:
         StateMssg = "Sorry, cannot save last operating state\n" + StateMssg
         wx.MessageBox(StateMssg, 'Info', wx.OK | wx.ICON_INFORMATION)

   def set_config(self):
      """ Get and distribute the main cfg values.

      Set installation specific config values for this module
      and module getradiostream.
      """

      CreateLocResult = True
      CreateLocVal = ""

      #*** Return state: 0 = fail, 1 = ok ***
      #    final state set by get_cfg_settings
      RtnStat = 0
      (RtnStat, RtnMssg, InitValues) = \
          cfginit.get_cfg_settings(self.LastStateFile)
      if not RtnStat:
         #*** MSSG LEVEL CRITICAL ***
         #*** Calling fcn will display the mssg ***
         pass
      else:
         if self.appDebugLevel >= 2:
            logging.debug("InitValues dictionary:")
            keylist = InitValues.keys()
            #keylist.sort()
            for keyval in keylist:
               logging.debug("%-25s   %-s" % (keyval, InitValues[keyval]))

         if os.path.exists(InitValues['DefMusicLoc']):
            self.DefMusicDir = InitValues['DefMusicLoc']
         else:
            (CreateLocResult, CreateLocVal) = \
                self.create_music_loc(InitValues['DefMusicLoc'])
            if CreateLocResult:
               self.DefMusicDir = CreateLocVal

         if CreateLocResult:
            if InitValues['EnableLog'] == 'True':
               self.IsLogging = True

            self.LastStreamName = InitValues['LastState'][0]
            self.LastEndTime = InitValues['LastState'][1]

            #*** If any of these don't exist don't allow stream actions to
            #*** take place.
            if len(InitValues['StreamRipLoc']) > 0 and \
                  len(InitValues['StreamNames']) > 0:
               self.StreamRipLoc = InitValues['StreamRipLoc']
               self.StreamName = InitValues['StreamNames']
               self.StreamURL = InitValues['StreamURLs']
               self.StreamLoc = InitValues['StreamLocs']

      return (RtnStat, RtnMssg)
      #------------------------------------------------------------------------

   def create_music_loc(self, DefLoc):
      """ Create the DefMusicLoc or stream file directory
      if it does not exist.

      Return an error if dir creation fails
      or if the DefMusicLoc is empty.
      But, ask for permission first.

      Input Arg:
        DefLoc - the full path to be created
      Return Val:
        Two value tuple
          - RtnState: False = fail, True = success
          - NewDefLoc - The path created if successful or
                        empty string if fail.
      """

      NewDefLoc = DefLoc.strip()
      RtnState = False
      RtnVal = (RtnState, '')

      if NewDefLoc == "":
         Mssg = "The default music location has not been defined.\n" \
                "Do you want to set its location now?"
      else:
         Mssg = "The location %s does not exist, do you want me to " \
                "create it?" % DefLoc

      MssgAns = wx.MessageBox(Mssg, 'Confirm',
                              wx.YES_NO | wx.ICON_QUESTION)

      if MssgAns == wx.YES:
         if NewDefLoc == "":
            DefLoc = self.on_new_dir()

            if DefLoc == "":
               Mssg = "No directory location was chosen\n" \
                      "Create music location will be bypassed for now"
               wx.MessageBox(Mssg, 'Info', wx.OK | wx.ICON_INFORMATION)
               return (RtnState, '')
            else:
               return (True, DefLoc)

         try:
            os.makedirs(NewDefLoc)
            RtnVal = (True, NewDefLoc)
         except IOError, (errno, strerror):
            Mssg = "Create music location IO error(%s): %s" \
                   % (errno, strerror)
            wx.MessageBox(Mssg, 'Error', wx.OK | wx.ICON_ERROR)
            logging.error(Mssg)
         except Exception, ex:
            Mssg = "Create music location error: %s" % ex
            wx.MessageBox(Mssg, 'Error', wx.OK | wx.ICON_ERROR)
            logging.error(Mssg)

      return RtnVal
      #------------------------------------------------------------------------

   def on_new_dir(self):
      """  Show the DirDialog. Return the chosen directory. """

      RtnDir = ""
      DlgAns = wx.DirDialog(self, "Choose a directory:",
                            style=wx.DD_DEFAULT_STYLE
                            #| wx.DD_DIR_MUST_EXIST
                            #| wx.DD_CHANGE_DIR
                            )
      if DlgAns.ShowModal() == wx.ID_OK:
         #Mssg = "You chose %s" % dlg.GetPath()
         #wx.MessageBox(Mssg, 'Info', wx.OK | wx.ICON_INFORMATION)
         RtnDir = DlgAns.GetPath()

      DlgAns.Destroy()
      return RtnDir

   def create_menu(self):
      """ Create all menu items and bind event methods. """

      menubar = wx.MenuBar()
      Utility = wx.Menu()
      mExit = wx.Menu()
      #mGetInfo = wx.Menu()
      AboutMenu = wx.Menu()

      self.ImportStreamMenu = Utility.Append(wx.ID_ANY, "&Import Streams")
      self.EmptyLogMenu = Utility.Append(wx.ID_ANY, "&Truncate Log")
      self.FileCleanMoveMenu = Utility.Append(wx.ID_ANY, "&Clean File Names")

      Utility.AppendSeparator()
      #self.mp3StreamMenu = MP3.Append(wx.ID_ANY, 'Get Stream')
      self.LogStreamMenu = Utility.Append(wx.ID_ANY, 'Save Stream Progress',
                                          "Toggle Stream Progress Logging",
                                          kind=wx.ITEM_CHECK)
      Utility.Check(self.LogStreamMenu.GetId(), True)

      self.ExitItem = mExit.Append(wx.ID_EXIT, "E&xit GetNetStream")
      self.AboutItem = AboutMenu.Append(wx.ID_ANY, "About &GetNetStream")

      self.Bind(wx.EVT_MENU, self.clean_file_names, self.FileCleanMoveMenu)
      self.Bind(wx.EVT_MENU, self.get_new_streams, self.ImportStreamMenu)
      self.Bind(wx.EVT_MENU, self.on_exit, self.ExitItem)
      self.Bind(wx.EVT_MENU, self.truncate_log_file, self.EmptyLogMenu)
      self.Bind(wx.EVT_MENU, self.enable_stream_log, self.LogStreamMenu)
      self.Bind(wx.EVT_MENU, self.show_about, self.AboutItem)

      # Logging true/false is set in the cfg file
      self.EmptyLogMenu.Enable(self.IsLogging)

      menubar.Append(Utility, '&Utility')
      menubar.Append(mExit, 'E&xit')
      menubar.Append(AboutMenu, '&About')
      self.SetMenuBar(menubar)
      #------------------------------------------------------------------------

   def on_exit(self, event):
      """ Exit menu action, ok to shutdown. """
      self.ProgramShutdownOK = True
      self.save_last_state()
      self.Close(True)
      #------------------------------------------------------------------------

   def clean_file_names(self, event):
      CleanNewFiles = cleanmove.CleanStreamFilesDialog(None, -1,
                             title='Clean and Move or Copy New Stream Files')
      CleanNewFiles.get_filters()
      myresult = CleanNewFiles.ShowModal()
      CleanNewFiles.Destroy()

   def show_about(self, event):
      """ Show the about dialog box """
      cfginit.OnAboutBox()

   def truncate_log_file(self, event):
      """ Empty the current active log if requested. """

      MssgAns = wx.MessageBox("Empty the log file?", 'Confirm',
                              wx.YES_NO | wx.ICON_QUESTION)

      if MssgAns == wx.YES:
         if os.path.exists('showmssg.log'):
            try:
               fo = open('showmssg.log', 'w')
               fo.close()
            except IOError as e:
               Mssg = "I/O error({0}): {1}".format(e.errno, e.strerror)
               wx.MessageBox(Mssg, 'Info', wx.OK | wx.ICON_ERROR)
               logging.error(Mssg)
            except:
               Mssg = "Unexpected error: %s" % sys.exc_info()[0]
               wx.MessageBox(Mssg, 'Info', wx.OK | wx.ICON_ERROR)
               logging.error(Mssg)
      #------------------------------------------------------------------------

   def get_new_streams(self, event):
      """ Get new values from a .pls playlist file.

      Add user selected values to the cfg file
      and the select ctrl for immediate use.
      """

      mynewstream = cfginit.GetNewStreamsDialog(None, -1,
                                title='Choose New Streams From pls File')
      mynewstream.DefMusicDir = self.DefMusicDir
      myresult = mynewstream.ShowModal()

      #*** Use the get_response function to retrieve new values to update
      #     the drop down list (self.StreamSelect)
      #    and global list structures (self.StreamName, self.StreamURL,
      #    self.StreamLoc)
      (NewNames, NewURLs, NewLocs) = mynewstream.get_response()
      if myresult == wx.ID_OK:
         if len(NewNames) > 0:
            self.StreamSelect.AppendItems(NewNames)
            self.StreamName.extend(NewNames)
            self.StreamURL.extend(NewURLs)
            self.StreamLoc.extend(NewLocs)
      else:
         pass

      mynewstream.Destroy()
      #------------------------------------------------------------------------

   def enable_stream_log(self, event):
      """ Turn on logging of song capture info. """

      if self.LogStreamMenu.IsChecked():
         # Menu item is now checked
         getradiostream.DoLog = True
      else:
         # Menu item is now unchecked
         getradiostream.DoLog = False
      #------------------------------------------------------------------------

   # ****************** Begin get radio stream processing *****************
   def init_stream_ctrls(self):
      """ Create and place all stream controls.

      This is intended to be called only at application start up time.
      """

      if len(self.StreamName) == 0:
         self.StreamName.append("No Streams")
         self.StreamURL.append("No Streams")
         self.StreamLoc.append("No Streams")

      maingui.show_stream_ctrls(self, self.StreamName)
      #------------------------------------------------------------------------

   def new_stream_selected(self, event):
      """ Update the labels when a new value has been chosen from the
      StreamSelect combo box.
      """

      Mssg = ""
      self.MainStatusBar.SetStatusText(Mssg, 0)
      StreamVals = maingui.get_stream_session_vals(self, True)
      #------------------------------------------------------------------------

   def start_stream(self, event):
      """ Start button clicked. Start a stream capture session. """

      self.MainStatusBar.SetStatusText("", 0)
      StreamVals = maingui.get_stream_session_vals(self, False)

      #*** Before continuing further, check that the selected
      #    'StreamLoc' dir exists. If not, ask if it should be created.
      #    Don't allow the process to continue until the dir exists and
      #    is valid. So there!
      RunState = True
      CreateLocVal = ""
      if not os.path.exists(StreamVals['StreamLoc']):
         (RunState, CreateLocVal) = \
            self.create_music_loc(StreamVals['StreamLoc'])
         if RunState:
            StreamVals['StreamLoc'] = CreateLocVal

      if RunState:
         # If loc exists or create was successful, we're good to go,
         # otherwise there is nothing left to do.
         maingui.disable_stream_action_ctrls(self)

         StreamArgs = (self, self.StreamRipLoc, StreamVals['StreamName'],
                       StreamVals['StreamURL'], StreamVals['StreamLoc'],
                       StreamVals['StreamET'])

         # Need to run the streaming function in a thread to retain control
         # of the UI. This very simple usage does the trick.
         self.StreamChild = threading.Thread(target=getradiostream.get_stream,
                                             name="GetNetStream",
                                             args=StreamArgs)
         self.StreamChild.start()
      #------------------------------------------------------------------------

   def end_stream_session(self, event):
      """ End Session means gracefully, but firmly, gather all your children
      and prepare to end your day at the beach, we gotta head for home.
      And when ending gracefully, save the last operating state. That
      condition will be used at start up to continue where we left off.
      """

      OkToShutDown = self.end_this_session()
      if OkToShutDown:
         self.ProgramShutdownOK = True
         self.save_last_state()
         self.Close(True)    # If requested end this application, we are done
      else:
         maingui.enable_stream_action_ctrls(self)
      #------------------------------------------------------------------------

   def end_this_session(self):
      """ Check if an active stream session thread is in progress before
      allowing the application to shut down.

      If no active threads, signal ok to end.
      If an active thread, wait for it to end, then signal back that condition
      from a message box.

      Return Val:
        True: ok to shut down.
        False: don't shut down. Set the controls to enabled and
        just end the thread but keep the application alive.
      """

      # Signal to the thread: Hey, stop streaming!
      getradiostream.StopTheStream = True
      MssgAns = None

      # ThreadCnt of 1 is the main process.
      # If only 1 thread don't bother asking permission to end the program.
      if threading.activeCount() > 1:
         # Give the get_stream while loop time to process the shutdown request
         time.sleep(2)
         self.MainStatusBar.SetStatusText("02 - ThreadCnt: " +
                                          str(threading.activeCount()), 0)
         ShutdownMssg = "Ok to stop the stream and close this program?"
         MssgAns = wx.MessageBox(ShutdownMssg, 'Confirm',
                                 wx.YES_NO | wx.ICON_QUESTION)

      EndMssg = ""
      RightNow = time.time()
      WaitDelay = RightNow + 4
      ThreadCnt = threading.activeCount()
      while threading.activeCount() > 1:
         self.MainStatusBar.SetStatusText("0 - ThreadCnt: " +
                                          str(threading.activeCount()), 0)
         if time.time() > WaitDelay:
            self.MainStatusBar.SetStatusText("1 - ThreadCnt: " +
                                             str(threading.activeCount()), 0)
            EndMssg = "Child thread is not responding to the shutdown request"
            if MssgAns == wx.YES:
               EndMssg += "\nGetNetStream will now end"
            wx.MessageBox(EndMssg, 'Info', wx.OK | wx.ICON_INFORMATION)
            break

      # Only show this mssg if there was an active thread and we had to wait
      # for some portion of the delay period.
      if len(EndMssg) == 0 and ThreadCnt > 1:
         self.MainStatusBar.SetStatusText("2 - ThreadCnt: " +
                                          str(threading.activeCount()), 0)
         EndMssg = "Child process shutdown normally"
         if MssgAns == wx.YES:
            EndMssg += "\nGetNetStream will now end"
         wx.MessageBox(EndMssg, 'Info', wx.OK | wx.ICON_INFORMATION)

      self.MainStatusBar.SetStatusText("3 - ThreadCnt: " +
                                       str(threading.activeCount()), 0)

      if MssgAns != wx.NO:
         return True
      else:
         return False

   def pause_stream(self, event):
      """ Set the flag variable to indicate the Pause button was clicked.

      And restore the stream action controls, but keep the application alive.
      """

      getradiostream.StopTheStream = True
      self.reset_stream_action_ctrls()
      #------------------------------------------------------------------------

   def reset_stream_action_ctrls(self):
      maingui.enable_stream_action_ctrls(self)
      #------------------------------------------------------------------------

   def clear_stream_list_content(self, event):
      if self.StreamListCtrl.GetItemCount() > 0:
         maingui.CurrentStreamItem = -1
         self.StreamListCtrl.DeleteAllItems()
      #------------------------------------------------------------------------

   def clear_connect_items(self, event):
      self.StreamConnectList.Clear()
      #------------------------------------------------------------------------

   def add_new_connect_items(self, ConnectListItems):
      maingui.add_connect_items(self, ConnectListItems)
      #------------------------------------------------------------------------

   def add_new_connect_item(self, ConnectListItem):
      maingui.AddConnectItem(self, ConnectListItem)
      #------------------------------------------------------------------------

   def insert_stream_content(self, ContentStr):
      maingui.insert_new_stream_list_item(self, ContentStr)
      #------------------------------------------------------------------------

   def update_stream_content(self, ContentStr):
      maingui.update_stream_list_item(self, ContentStr)
      #------------------------------------------------------------------------

   def show_end_time_help(self, event):
      Mssg = "Stream End Time hh = 00-23, mm = 00-59"
      self.MainStatusBar.SetStatusText(Mssg, 0)

   # *** These next 5 event methods are not used.
   #     Their definition in a bind method call
   #     deactivates any click events assigned to
   #     the same control.
   #def start_bttn_hover(self, event):
   #   Mssg = ""
   #   self.MainStatusBar.SetStatusText(Mssg, 0)

   #def pause_bttn_hover(self, event):
   #   Mssg = ""
   #   self.MainStatusBar.SetStatusText(Mssg, 0)

   #def clear_list_bttn_hover(self, event):
   #   Mssg = ""
   #   self.MainStatusBar.SetStatusText(Mssg, 0)

   #def stream_select_hover(self, event):
   #   Mssg = ""
   #   self.MainStatusBar.SetStatusText(Mssg, 0)

   #def clear_connect_bttn_hover(self, event):
   #   Mssg = ""
   #   self.MainStatusBar.SetStatusText(Mssg, 0)
   # ****************** End get radio stream processing *****************
# ----------------------- End of class MainStreamFrame ------------------------


class ShowStreamMain(wx.App):
   """ Init the main frame. """

   def OnInit(self):
      DebugLevel = 1   # The higher the debug level, the more mssg logging
      self.frame = MainStreamFrame(None, wx.ID_ANY,
                                   "Get Internet Radio Streams", DebugLevel)
      self.frame.Centre()
      self.frame.Show()
      return True


def set_log_state():
   """ Find out if the cfg file says to turn on logging.

   If supplied, just return the value from the cfg file
   as a string value.
   The calling fcn will determine the correct action.
   """

   # To support starting gns.py via a launcher, make sure the
   # location of this module is the current working directory.
   # Otherwise, right off the bat we won't be able to find the
   # config file.
   thisDir = os.path.dirname(os.path.abspath(sys.argv[0]))
   #print "current directory is: " + thisDir
   os.chdir(thisDir)

   LogState = "False"
   try:
      for line in open(cfginit.CfgFileName, 'r'):
         TempStr = line.strip()
         if len(TempStr) > 0 and TempStr[0] != "#":
            (theKey, theValue) = TempStr.split("=")
            if theKey == "EnableLog":
               LogState = theValue
               break
   except IOError, (errno, strerror):
      RtnMssg = "InitMain: Config file open error(%s): %s" % (errno, strerror)
      print RtnMssg
   except:
      RtnMssg = "InitMain: Unexpected config file open error: ", \
                sys.exc_info()[0]
      print RtnMssg
   finally:
      #RtnMssg += "\nConfig file settings read complete"
      pass

   #print "*%s*" % LogState
   return LogState


def init_main():
   #print "Log File Exists: %s" % os.path.exists('showmssg.log')
   # First thing to do; establish run time logging settings.
   if os.path.exists('showmssg.log'):
      DateStampNow = datetime.datetime.now()
      NewName = 'showmssg_' + DateStampNow.strftime("%Y%m%d_%H%M") + '.log'
      os.rename('showmssg.log', NewName)

   if set_log_state() == "True":
      # Turn on logging
      ShowLogFormat = '%(levelname)-8s: %(asctime)-15s: %(module)-15s: '
      ShowLogFormat += '%(funcName)-15s: %(lineno)5d: %(message)s'
      logging.basicConfig(filename='showmssg.log', format=ShowLogFormat,
                          level=logging.DEBUG)
      logging.info('logging is turned on...')


if __name__ == "__main__":
   init_main()
   app = ShowStreamMain(0)
   app.MainLoop()
